package cn.js189.uqc.util;

import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import com.jcraft.jsch.ChannelSftp.LsEntry;

/**
 * 
 * <Description> <br> 
 *  
 * @author yangyang<br>
 * @version 1.0<br>
 * @taskId <br>
 * @CreateDate 2019年6月27日 <br>
 */
public class SFTPUtils implements AutoCloseable
{
    private static final Logger logger = LoggerFactory.getLogger(SFTPUtils.class);
 
  private String host;//服务器连接ip
  private String username;//用户名
  private String password;//密码
  private int port = 22;//端口号
  private ChannelSftp sftp = null;
  private Session sshSession = null;
 
  public SFTPUtils(){}
 
  public SFTPUtils(String host, int port, String username, String password)
  {
    this.host = host;
    this.username = username;
    this.password = password;
    this.port = port;
  }
 
  public SFTPUtils(String host, String username, String password)
  {
    this.host = host;
    this.username = username;
    this.password = password;
  }
 
  /**
   * 通过SFTP连接服务器
   */
  public void connect()
  {
    try
    {
      JSch jsch = new JSch();
      jsch.getSession(username, host, port);
      sshSession = jsch.getSession(username, host, port);
      if (logger.isInfoEnabled())
      {
          logger.debug("Session created.");
      }
      sshSession.setPassword(password);
      Properties sshConfig = new Properties();
      sshConfig.put("StrictHostKeyChecking", "no");
      sshSession.setConfig(sshConfig);
      sshSession.connect();
      if (logger.isInfoEnabled())
      {
          logger.debug("Session connected.");
      }
      Channel channel = sshSession.openChannel("sftp");
      channel.connect();
      if (logger.isInfoEnabled())
      {
          logger.debug("Opening Channel.");
      }
      sftp = (ChannelSftp) channel;
      if (logger.isInfoEnabled())
      {
          logger.debug("Connected to {}" , host);
      }
    }
    catch (Exception e)
    {
        logger.debug(e.getMessage());
    }
  }
 
  /**
   * 关闭连接
   */
  public void disconnect()
  {
    if (this.sftp != null&&this.sftp.isConnected())
    {
        this.sftp.disconnect();
        if (logger.isInfoEnabled())
        {
            logger.debug("sftp is closed already");
        }
    }
    if (this.sshSession != null&&this.sshSession.isConnected())
    {
        this.sshSession.disconnect();
        if (logger.isInfoEnabled())
        {
            logger.debug("sshSession is closed already");
        }
    }
  }
 
  
  /**
   * 下载单个文件
   * @param remoteFileName：下载文件名
   * @param localPath：本地保存目录(以路径符号结束)
   * @param localFileName：保存文件名
   * @return
   */
  public boolean downloadFile(String remotePath, String remoteFileName,String localPath, String localFileName)
  {
      //防止文件夹不存在，先提前创建
      File dicfile = new File(localPath);
      if (!dicfile.exists()) {
          dicfile.mkdirs();
      }
    File file = new File(localPath + localFileName);
    try(FileOutputStream fieloutput= new FileOutputStream(file))
    {
      sftp.get(remotePath + remoteFileName, fieloutput);
      if (logger.isInfoEnabled())
      {
          logger.debug("===DownloadFile:{}" , remoteFileName);
      }
      return true;
    }
    catch (Exception e)
    {
      logger.debug(e.getMessage());
    }
    return false;
  }
  
  /**
   * 上传单个文件
   * @param remotePath：远程保存目录
   * @param remoteFileName：保存文件名
   * @param localPath：本地上传目录(以路径符号结束)
   * @param localFileName：上传的文件名
   * @return
   */
  public boolean uploadFile(String remotePath, String remoteFileName,String localPath, String localFileName)
  {
    File file = new File(localPath + localFileName);
    try(FileInputStream in= new FileInputStream(file))
    {
      createDir(remotePath);
      sftp.put(in, remoteFileName);
      return true;
    }
    catch (Exception e)
    {
      logger.debug(e.getMessage());
    }
    return false;
  }
  
  /**
   * 以流的形式上传单个文件
   * @param remotePath：远程保存目录
   * @param remoteFileName：保存文件名
   * @param in：上传文件流
   * @return
   */
  public boolean uploadFileByFileInputStream(String remotePath, String remoteFileName,InputStream in)
  {
    try
    {
      createDir(remotePath);
      sftp.put(in, remoteFileName);
      return true;
    }
    catch (Exception e)
    {
      logger.debug(e.getMessage());
    }
    return false;
  }
 
  
 
 
  /**
   * 创建目录
   * @param createpath
   * @return
   */
  public boolean createDir(String createpath)
  {
    try
    {
      if (isDirExist(createpath))
      {
        this.sftp.cd(createpath);
        return true;
      }
      String [] pathArry = createpath.split("/");
      StringBuilder filePath = new StringBuilder("/");
      for (String path : pathArry)
      {
        if (path.equals(""))
        {
          continue;
        }
        filePath.append(path + "/");
        if (isDirExist(filePath.toString()))
        {
          sftp.cd(filePath.toString());
        }
        else
        {
          // 建立目录
          sftp.mkdir(filePath.toString());
          // 进入并设置为当前目录
          sftp.cd(filePath.toString());
        }
 
      }
      this.sftp.cd(createpath);
      return true;
    }
    catch (SftpException e)
    {
      logger.debug(e.getMessage());
    }
    return false;
  }
 
  /**
   * 判断目录是否存在
   * @param directory
   * @return
   */
  public boolean isDirExist(String directory)
  {
    boolean isDirExistFlag = false;
    try
    {
      SftpATTRS sftpATTRS = sftp.lstat(directory);
      isDirExistFlag = true;
      return sftpATTRS.isDir();
    }
    catch (Exception e)
    {
      if ("no such file".equalsIgnoreCase(e.getMessage()))
      {
        isDirExistFlag = false;
      }
    }
    return isDirExistFlag;
  }
 
  /**
   * 删除stfp文件
   * @param directory：要删除文件所在目录
   * @param deleteFile：要删除的文件
   */
  public void deleteSFTP(String directory, String deleteFile)
  {
    try
    {
      sftp.rm(directory + deleteFile);
      if (logger.isInfoEnabled())
      {
          logger.debug("delete file success from sftp.");
      }
    }
    catch (Exception e)
    {
        logger.debug(e.getMessage());
    }
  }
 
  /**
   * 如果目录不存在就创建目录
   * @param path
   */
  public void mkdirs(String path)
  {
    File f = new File(path);
 
    String fs = f.getParent();
 
    f = new File(fs);
 
    if (!f.exists())
    {
      f.mkdirs();
    }
  }
 
  /**
   * 列出目录下的文件
   * 
   * @param directory：要列出的目录
   */
  public List<String> listFiles(String directory) throws SftpException
  {
      List fileNameList = new ArrayList();
      Vector remoteFile = sftp.ls(directory);
	  for (Object o : remoteFile) {
		  LsEntry lsEntry = (LsEntry) o;
		  logger.debug("lsEntry----------------:,{}", lsEntry.getFilename());
		  fileNameList.add(lsEntry.getFilename());
	  }
    return fileNameList;
  }
 
  public String getHost()
  {
    return host;
  }
 
  public void setHost(String host)
  {
    this.host = host;
  }
 
  public String getUsername()
  {
    return username;
  }
 
  public void setUsername(String username)
  {
    this.username = username;
  }
 
  public String getPassword()
  {
    return password;
  }
 
  public void setPassword(String password)
  {
    this.password = password;
  }
 
  public int getPort()
  {
    return port;
  }
 
  public void setPort(int port)
  {
    this.port = port;
  }
 
  public ChannelSftp getSftp()
  {
    return sftp;
  }
 
  public void setSftp(ChannelSftp sftp)
  {
    this.sftp = sftp;
  }

/**
 * Description: <br> 
 *  
 * @author yangyang<br>
 * @throws Exception <br>
 */ 
@Override
public void close() throws Exception {
    disconnect();
}
   
}